package hw02;

import java.io.StringWriter;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;

public class WebPage {
	
	protected HttpServletRequest request;
	protected Document document;
	protected Element body;
	protected Element head;
	protected Element title;
	private int uid = 0;
	
	public WebPage(HttpServletRequest request) {
		this.request = request;
	}

	protected void initDocument() {
		Element html = document.getDocumentElement();
		
		head = document.createElement("head");
		html.appendChild(head);
		
		Element metaContent = document.createElement("meta");
		metaContent.setAttribute("http-equiv", "Content-type");
		metaContent.setAttribute("content", "text/html;charset=UTF-8");
		head.appendChild(metaContent);

		body = document.createElement("body");
		html.appendChild(body);
		
		body.appendChild(createIdentInfo());
	}
	
	protected Element createIdentInfo() {
		Element identInfoDiv = createSection("Identifying Information");
		
		Element home = document.createElement("a");
		home.setAttribute("href", "?");
		home.setTextContent("Home");
		identInfoDiv.appendChild(home);

		Element titleElement = document.createElement("a");
		titleElement.setAttribute("href", "http://cs.umaine.edu/~chaw/cos480/");
		titleElement.setTextContent("COS 480 Fall 2011 HW02");
		identInfoDiv.appendChild(label("Title:", titleElement));

		Element nameElement = document.createElement("a");
		nameElement.setAttribute("href", "http://cs.umaine.edu/~jcbunix/");
		nameElement.setTextContent("Joshua Belanger");
		identInfoDiv.appendChild(label("Name:", nameElement));
		
		Element prefEmailElement = document.createElement("a");
		prefEmailElement.setAttribute("href", "mailto://joshua.belanger@umit.maine.edu");
		prefEmailElement.setTextContent("joshua.belanger@umit.maine.edu");
		identInfoDiv.appendChild(label("Preferred Email:", prefEmailElement));

		Element gandalfIDElement = document.createElement("span");
		gandalfIDElement.setTextContent("jcbunix");
		identInfoDiv.appendChild(label("Gandalf Login ID:", gandalfIDElement));
		
		Element postgreIDElement = document.createElement("span");
		postgreIDElement.setTextContent("jcbunix");
		identInfoDiv.appendChild(label("Postgre SQL ID:", postgreIDElement));
		
		return identInfoDiv;
	}
	
	protected Element createSection(String title) {
		Element div = document.createElement("div");
		Element h2 = document.createElement("h2");
		h2.setTextContent(title);
		div.appendChild(h2);
		return div;
	}
	
	public Document getDocument() {
		if(document == null) {
			uid = 0;
			try {
				DocumentBuilderFactory docBuilderFac = DocumentBuilderFactory.newInstance();
				DocumentBuilder docBuilder = docBuilderFac.newDocumentBuilder();
				DocumentType docType = docBuilder.getDOMImplementation().createDocumentType(
					"html",
					"-//W3C//DTD XHTML 1.1//EN",
					"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
				);
				document = docBuilder.getDOMImplementation().createDocument(
					"http://www.w3.org/1999/xhtml",
					"html",
					docType
				);
				
				initDocument();

				Element w3c = document.createElement("p");
				body.appendChild(w3c);
				Element a = document.createElement("a");
				w3c.appendChild(a);
				a.setAttribute("href", "http://validator.w3.org/check?uri=referer");
				Element img = document.createElement("img");
				a.appendChild(img);
				img.setAttribute("src", "http://www.w3.org/Icons/valid-xhtml11");
				img.setAttribute("alt", "Valid XHTML 1.1!");
				img.setAttribute("height", "31");
				img.setAttribute("width", "88");
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			}
		}
		return document;
	}
	
	@Override
	public String toString() {
        TransformerFactory transFac = TransformerFactory.newInstance();
        Transformer transformer = null;
		try {
			transformer = transFac.newTransformer();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		}
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        if(getDocument().getDoctype() != null) {
        	transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, getDocument().getDoctype().getPublicId());
        	transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, getDocument().getDoctype().getSystemId());
        }
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(getDocument());
        
        try {
			transformer.transform(source, result);
		} catch (TransformerException e) {
			e.printStackTrace();
		}
        
        return sw.toString();
	}
	
	protected Element span(Element element) {
		Element span = document.createElement("span");
		span.appendChild(element);
		return span;
	}
	
	protected Element label(String text, Element element) {
		uid++;
		element.setAttribute("id", "id-" + uid);
		
		Element label = document.createElement("label");
		label.setTextContent(text);
		label.setAttribute("for", "id-" + uid);
		
		Element div = document.createElement("div");
		div.appendChild(label);
		div.appendChild(element);
		return div;
	}
	
	@SuppressWarnings("deprecation")
	protected String encode(Map<String, String> params) {
		List<String> encoded = new LinkedList<String>();
		for(String paramName : params.keySet()) {
			encoded.add(paramName+"="+URLEncoder.encode(params.get(paramName)));
		}

		String implode = "";
		Iterator<String> iter = encoded.iterator(); 
		while(iter.hasNext()) {
			implode += iter.next();
			if(iter.hasNext()) {
				implode += "&";
			}
		}
		return implode;
	}

}